﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace SPPlus.CustomField.JqueryScript
{
    public class JqueryScriptFieldEditor : UserControl, IFieldEditor
    {

        #region Fields
        protected TextBox txtJqueryLibrary;
        protected TextBox txtLibraries;
        protected TextBox txtScript;
        protected CheckBoxList chklstFormMode;
        #endregion

        #region Properties
        bool IFieldEditor.DisplayAsNewSection
        {
            get { return false; }
        }
        SPList List
        {
            get { return SPContext.Current.List; }
        }
        #endregion

        #region Constructor
        public JqueryScriptFieldEditor()
        {
            txtJqueryLibrary = null;
            txtLibraries = null;
            txtScript = null;
            chklstFormMode = null;
        }
        #endregion

        #region Initialise the field
        void IFieldEditor.InitializeWithField(SPField field)
        {
            if (!IsPostBack)
                DisplaySavedData(field);
        }
        #endregion
        
        #region Save the configuration
        void IFieldEditor.OnSaveChange(SPField field, bool isNewField)
        {
            JqueryScriptField customfield = (JqueryScriptField)field;

            XmlDocument xmlDoc = FormatFieldConfigurationDataAsXml();
            string value = xmlDoc.OuterXml;
            if (isNewField)
                customfield.CacheCustomProperty(value);
            else
                customfield.CustomProperty = value;

            SetFieldVisibilityInList(customfield, xmlDoc);
        }
        #endregion

        #region Manipulate the data for persisting
        /// <summary>
        /// Format the entered data as XML for storing in the field properties
        /// </summary>
        /// <returns>An <see cref="XmlDocument"/> instance containing the data</returns>
        private XmlDocument FormatFieldConfigurationDataAsXml()
        {
            XmlDocument xmlDoc = new XmlDocument();
            XmlNode xmlNode = xmlDoc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
            xmlDoc.AppendChild(xmlNode);
            XmlElement xmlRoot = xmlDoc.CreateElement("", "fielddata", "");
            xmlDoc.AppendChild(xmlRoot);

            AddJQueryLibrary(xmlDoc);
            AddLibraries(xmlDoc);
            AddScript(xmlDoc);
            AddScriptVisibility(xmlDoc);

            return xmlDoc;
        }
        private void AddJQueryLibrary(XmlDocument xmlDoc)
        {
            if (!string.IsNullOrEmpty(txtJqueryLibrary.Text))
            {
                XmlElement xmlEl = xmlDoc.CreateElement("", Constants.JQUERYLIBRARY_XMLNODENAME, "");
                XmlCDataSection cData = xmlDoc.CreateCDataSection(txtJqueryLibrary.Text);
                xmlEl.AppendChild(cData);
                xmlDoc.ChildNodes[1].AppendChild(xmlEl);
            }
        }
        /// <summary>
        /// Add the JavaScript libraries to the configuration data for this field
        /// </summary>
        /// <param name="xmlDoc">The XmlDocument for the configuration data</param>
        private void AddLibraries(XmlDocument xmlDoc)
        {
            if (!string.IsNullOrEmpty(txtLibraries.Text))
            {
                XmlElement xmlEl = xmlDoc.CreateElement("", Constants.LIBRARIES_XMLNODENAME, "");
                XmlCDataSection cData = xmlDoc.CreateCDataSection(txtLibraries.Text);
                xmlEl.AppendChild(cData);
                xmlDoc.ChildNodes[1].AppendChild(xmlEl);
            }
        }
        /// <summary>
        /// Add the JavaScript to the configuration data for this field
        /// </summary>
        /// <param name="xmlDoc">The XmlDocument for the configuration data</param>
        private void AddScript(XmlDocument xmlDoc)
        {
            string script = txtScript.Text;
            XmlElement xmlEl = xmlDoc.CreateElement("", Constants.SCRIPT_XMLNODENAME, "");
            XmlCDataSection cData = xmlDoc.CreateCDataSection(script);
            xmlEl.AppendChild(cData);
            xmlDoc.ChildNodes[1].AppendChild(xmlEl);
        }
        /// <summary>
        /// Add configuration data specifying the form control modes in which the Javascript is to display 
        /// </summary>
        /// <param name="xmlDoc">The XmlDocument for the configuration data</param>
        private void AddScriptVisibility(XmlDocument xmlDoc)
        {
            StringBuilder sb = new StringBuilder();
            foreach (ListItem item in chklstFormMode.Items)
            {
                if (item.Selected)
                    sb.Append(item.Value + ";");
            }

            XmlElement xmlEl = xmlDoc.CreateElement("", Constants.VISIBLEINCONTROLMODES_XMLNODENAME, "");
            xmlEl.InnerText = sb.ToString();
            xmlDoc.ChildNodes[1].AppendChild(xmlEl);
        }
        #endregion

        #region Retrieving saved data
        private void DisplaySavedData(SPField field)
        {
            if (field != null)
            {
                JqueryScriptField customfield = (JqueryScriptField)field;
                string xmlAsString = customfield.CustomProperty;
                XmlDocument xmlDoc = new XmlDocument();
                try
                {
                    xmlDoc.LoadXml(xmlAsString);

                    WriteXmlTextToTextBox(xmlDoc, Constants.JQUERYLIBRARY_XMLNODENAME, txtJqueryLibrary);
                    WriteXmlTextToTextBox(xmlDoc, Constants.LIBRARIES_XMLNODENAME, txtLibraries);
                    WriteXmlTextToTextBox(xmlDoc, Constants.SCRIPT_XMLNODENAME, txtScript);
                    SetControlModeValues(xmlDoc);
                }
                catch { }
            }
        }
        private void WriteXmlTextToTextBox(XmlDocument xmlDoc, string xmlNodeName, TextBox textbox)
        {
            XmlNode selectedNode = xmlDoc.SelectSingleNode(string.Format("/fielddata/{0}", xmlNodeName));
            if (selectedNode != null)
                textbox.Text = selectedNode.InnerText;
        }
        private void SetControlModeValues(XmlDocument xmlDoc)
        {
            XmlNode selectedNode = xmlDoc.SelectSingleNode(string.Format("/fielddata/{0}", Constants.VISIBLEINCONTROLMODES_XMLNODENAME));
            if (selectedNode != null)
            {
                string controlModeValues = selectedNode.InnerText;
                if (!string.IsNullOrEmpty(controlModeValues))
                {
                    string[] modes = controlModeValues.Split(new char[] { ';' });
                    foreach (String mode in modes)
                    {
                        if (mode == "Display")
                            chklstFormMode.Items[0].Selected = true;
                        else if (mode == "Edit")
                            chklstFormMode.Items[1].Selected = true;
                        else if (mode == "New")
                            chklstFormMode.Items[2].Selected = true;
                    }
                }
            }
        }
        #endregion

        #region Set the base field visibility
        /// <summary>
        /// Set basic field visibility on the various forms - hide where script is not to be rendered
        /// </summary>
        /// <param name="customfield">The field instance to which to apply the visibility settings</param>
        /// <param name="xmlDoc">The <see cref="XmlDocument"/> document storing the config data</param>
        private void SetFieldVisibilityInList(JqueryScriptField customfield, XmlDocument xmlDoc)
        {
            XmlNode selectedNode = xmlDoc.SelectSingleNode(string.Format("/fielddata/{0}", Constants.VISIBLEINCONTROLMODES_XMLNODENAME));
            if (selectedNode != null)
            {
                string controlModeValues = selectedNode.InnerText;
                if (!string.IsNullOrEmpty(controlModeValues))
                {
                    customfield.ShowInDisplayForm = false;
                    customfield.ShowInEditForm = false;
                    customfield.ShowInNewForm = false;
                    customfield.ShowInVersionHistory = false;
                    customfield.ShowInViewForms = false;

                    string[] modes = controlModeValues.Split(new char[] { ';' });
                    foreach (string mode in modes)
                    {
                        if (mode == "Display")
                            customfield.ShowInDisplayForm = true;
                        else if (mode == "Edit")
                            customfield.ShowInEditForm = true;
                        else if (mode == "New")
                            customfield.ShowInNewForm = true;
                    }
                }
            }
        }        
        #endregion

    }
}
